import re
import pandas as pd
import sys
import io
import os
import chardet

global_read_data = ""
def global_read_data_init():
    global global_read_data
    global_read_data = ""
####################################################################################
# 设置标准输出编码为UTF-8
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
####################################################################################
class RegisterFileCreator:
    def __init__(self, name):
        self.name = f"{name}_register"
        self.source_file = f"{self.name}.c"
        self.include_file = f"{self.name}.h"
        self.registers = []  # 用于存储寄存器名称和地址
        self.end_guard = f"\n#endif // __{self.name.upper()}_H__\n"
        self.format_init()

    def include_file_init(self):
        # 写入头文件格式
        define_guard = f"#ifndef __{self.name.upper()}_H__\n#define __{self.name.upper()}_H__\n\n"
        struct_def = f"struct {self.name} {{\n"
        for reg_name, _ in self.registers:
            struct_def += f"    uint8_t {reg_name}[2];\n"
        struct_def += "};\n\n"
        with open(self.include_file, 'w', encoding='utf-8') as file:
            file.write(define_guard)
            file.write(struct_def)
            file.write(self.end_guard)

    def source_file_init(self):
        # 写入源文件格式
        with open(self.source_file, 'w', encoding='utf-8') as file:
            file.write(f"#include \"{self.include_file}\"\n\n")

    def format_init(self):
        self.include_file_init()
        self.source_file_init()

    def create_register_files(self, reg_name, reg_address):
        # 添加寄存器到列表
        self.registers.append((reg_name, reg_address))
        # 更新结构体定义
        self.update_struct_def()
        # 在源文件中添加初始化函数
        self.add_init_function()

    def update_struct_def(self):
        struct_def = f"struct {self.name} {{\n"
        for reg_name, _ in self.registers:
            struct_def += f"    unsigned char {reg_name}[2];\n"
        struct_def += "};\n\n"

        # 声明初始化函数
        init_func_decl = f"struct {self.name} init_{self.name}(void);\n\n"

        # 更新头文件中的结构体定义和初始化函数声明
        with open(self.include_file, 'r+', encoding='utf-8') as file:
            content = file.read()
            # 移除文件末尾的 'end_guard' 部分
            content = content.rsplit(self.end_guard, 1)[0]
            # 移除旧的 struct 定义和初始化函数声明
            content = content.split(f"struct {self.name} {{", 1)[0]
            content = content.split(f"struct {self.name} init_{self.name}(void);", 1)[0]
            file.seek(0)
            file.write(content)
            file.write(struct_def)
            file.write(init_func_decl)
            file.write(self.end_guard)




    def add_init_function(self):
        # 在源文件中添加初始化函数
        init_func = f"struct {self.name} init_{self.name}() {{\n"
        init_func += f"    struct {self.name} regs = {{\n"
        for reg_name, reg_address in self.registers:
            init_func += f"        .{reg_name} = {{0x{reg_address:02X}, 0x00}},\n"
        init_func += "    };\n"
        init_func += "    return regs;\n"
        init_func += "}\n\n"

        with open(self.source_file, 'w', encoding='utf-8') as file:
            file.write(f"#include \"{self.include_file}\"\n\n")
            file.write(init_func)
####################################################################################
class WriteConfigCreator:
    def __init__(self, name):
        self._name = name
        self.name = f"{name}_config"
        self.source_file = f"{ self.name}.c"
        self.include_file = f"{ self.name}.h"
        self.registers = []  # 用于存储寄存器名称和地址
        self.end_guard = f"\n#endif // __{self.name.upper()}_H__\n"
        self.format_init()
        self.function_begin = f"void {self.name}(void) {{\n    {self._name} = init_{self._name}_register();\n"
        self.function_end = f"\n}} // {self.name}_write end\n"

    def include_file_init(self):
        # 写入头文件格式
        define_guard = f"#ifndef __{self.name.upper()}_H__\n#define __{self.name.upper()}_H__\n\n"
        extern_struct_def = f"extern struct {self._name}_register {self._name};\n"
        # define_write_func = f"#define {self._name}_write(array)\n"
        # define_read_func = f"#define {self._name}_read(array)\n"
        function_name = f"void {self.name}(void);"
        with open(self.include_file, 'w', encoding='utf-8') as file:
            file.write(define_guard)
            file.write(extern_struct_def)
            # file.write(define_write_func)
            # file.write(define_read_func)
            file.write(function_name)
            file.write(self.end_guard)

    def source_file_init(self):
        # 写入源文件格式
        struct_def = f"struct {self._name}_register {self._name};\n"
        free_function_prefix = f"/**************{self._name}free write begin**************/\n"
        test_write = f"void {self._name}_write(unsigned char *array) {{\n\n}}\n"
        free_function_suffix = f"/**************{self._name}free write end**************/\n"
        # struct_init = f"{self._name} = init_{self._name}_register();\n"
        try:
            with open(self.source_file, 'r+', encoding='utf-8') as file:
                test = file.read()
                # 找到free_function_prefix的位置并删除它前面的所有内容
                prefix_index = test.find(free_function_prefix)
                if prefix_index != -1:
                    test = test[prefix_index + len(free_function_prefix):]

                # 找到free_function_suffix的位置并删除它后面的所有内容
                suffix_index = test.find(free_function_suffix)
                if suffix_index != -1:
                    test = test[:suffix_index]
                # 查找函数的开始部分
                test_write = test
        except FileNotFoundError:
            pass
        with open(self.source_file, 'w+', encoding='utf-8') as file:
            file.write(f"#include \"{self.include_file}\"\n#include \"{self._name}_register.h\"\n")
            file.write(struct_def)
            file.write(free_function_prefix)
            file.write(test_write)
            file.write(free_function_suffix)


    def format_init(self):
        #第一次初始化
        self.include_file_init()
        self.source_file_init()

    def write_config(self, register_name, register_data):
        # 写入寄存器配置
        write_data = f"    {self._name}.{register_name}[1] = 0x{register_data:02x};\n    {self._name}_write({self._name}.{register_name});\n"
        # 检查文件是否存在，如果不存在，则创建文件并写入函数的开始部分
        if not os.path.exists(self.source_file):
            with open(self.source_file, 'w', encoding='utf-8') as file:
                file.write(self.function_begin)
                file.write(self.function_end)
        
        # 读取现有文件内容
        with open(self.source_file, 'r+', encoding='utf-8') as file:
            content = file.read()
            # 查找函数的开始部分
            begin_index = content.find(self.function_begin)
            if begin_index != -1:
                # 移除函数的开始部分和结束部分
                content = content[:begin_index] + content[begin_index:].split(self.function_end, 1)[0]
            else:
                # 如果函数开始部分不存在，则添加它
                content += self.function_begin

            # 将新的配置行添加到函数体内
            content += write_data

            # 将函数的结束部分添加回文件
            content += self.function_end
        
        # 将修改后的内容写回文件
        with open(self.source_file, 'w', encoding='utf-8') as file:
            file.write(content)
####################################################################################
class ReadRegisterCreator:
    def __init__(self, name, number,formula):
        self._name = name
        self.number = number
        self.formula = formula
        self.name = f"{name}_read"
        self.source_file = f"{ self.name}_{self.number}.c"
        self.include_file = f"{ self.name}_{self.number}.h"
        self.registers = []  # 用于存储寄存器名称和地址
        self.end_guard = f"\n#endif // __{self.name.upper()}_H__\n"
        self.format_init()
        self.function_begin = f"unsigned int {self.name}_{self.number}(void) {{\n    unsigned int data = 0;\n"
        self.function_end = f"\t{self.formula}\n\treturn data;\n\n}} // {self.name} end\n"
    def include_file_init(self):
        # 写入头文件格式
        define_guard = f"#ifndef __{self.name.upper()}_H__\n#define __{self.name.upper()}_H__\n\n"
        # extern_struct_def = f"extern struct {self._name}_register {self._name};\n"

        function_name = f"unsigned int {self.name}_{self.number}(void);"
        with open(self.include_file, 'w', encoding='utf-8') as file:
            file.write(define_guard)
            # file.write(extern_struct_def)
            file.write(function_name)
            file.write(self.end_guard)

    def source_file_init(self):
        # 写入源文件格式
        # struct_def = f"struct {self._name}_register {self._name};\n"
        free_function_prefix = f"/**************{self._name}free write begin**************/\n"
        test_write = f"void {self._name}_read(unsigned char *array) {{\n\n}}\n"
        free_function_suffix = f"/**************{self._name}free write end**************/\n"
        # struct_init = f"{self._name} = init_{self._name}_register();\n"
        try:
            with open(self.source_file, 'r+', encoding='utf-8') as file:
                test = file.read()
                # 找到free_function_prefix的位置并删除它前面的所有内容
                prefix_index = test.find(free_function_prefix)
                if prefix_index != -1:
                    test = test[prefix_index + len(free_function_prefix):]

                # 找到free_function_suffix的位置并删除它后面的所有内容
                suffix_index = test.find(free_function_suffix)
                if suffix_index != -1:
                    test = test[:suffix_index]
                # 查找函数的开始部分
                test_write = test
        except FileNotFoundError:
            pass
        with open(self.source_file, 'w+', encoding='utf-8') as file:
            file.write(f"#include \"{self.include_file}\"\n#include \"{self._name}_register.h\"\n#include \"{self._name}_config.h\"\n")
            # file.write(struct_def)
            file.write(free_function_prefix)
            file.write(test_write)
            file.write(free_function_suffix)


    def format_init(self):
        #第一次初始化
        self.include_file_init()
        self.source_file_init()
    def read_config(self, register_name, register_data):
         # 写入寄存器配置
        write_data = f"    {self._name}_read({self._name}.{register_name});\n\tdata |= {self._name}.{register_name}[1] {register_data};\n\n"
        # 检查文件是否存在，如果不存在，则创建文件并写入函数的开始部分
        if not os.path.exists(self.source_file):
            with open(self.source_file, 'w', encoding='utf-8') as file:
                file.write(self.function_begin)
                file.write(self.function_end)

        with open(self.source_file, 'r+', encoding='utf-8') as file:
            content = file.read()
            # 查找函数的开始部分
            begin_index = content.find(self.function_begin)
            if begin_index != -1:
                # 移除函数的开始部分和结束部分
                content = content[:begin_index] + content[begin_index:].split(self.function_end, 1)[0]
            else:
                # 如果函数开始部分不存在，则添加它
                content += self.function_begin

            # 将新的配置行添加到函数体内
            content += write_data

            # 将函数的结束部分添加回文件
            content += self.function_end
        
        # 将修改后的内容写回文件
        with open(self.source_file, 'w', encoding='utf-8') as file:
            file.write(content)
####################################################################################
class MarkdownTableProcessor:
    def __init__(self, file_path):
        self.file_path = file_path
        self.df = self.parse_markdown_table()
        self.unique_df = self.create_unique_name_address_table(self.df)
        self.formula = self.formula_form_markdown()
    def formula_form_markdown(self):
        # 读取Markdown文件内容
        with open(self.file_path, 'rb') as file:
            result = chardet.detect(file.read())
        with open(self.file_path, 'r', encoding=result['encoding']) as file:
            formula = file.read()
        # 使用正则表达式找到"#### **表格开始**"和"#### **表格结束**"之间的内容
        formula = re.search(r'#### \*\*Formula_Start\*\*(.*?)#### \*\*Formula_End\*\*', formula, re.DOTALL).group(1)
        # print(formula)
        return formula.strip()
    def parse_markdown_table(self):
                # 读取Markdown文件内容
        with open(self.file_path, 'rb') as file:
            result = chardet.detect(file.read())
        with open(self.file_path, 'r', encoding=result['encoding']) as file:
            markdown_table = file.read()

        # 使用正则表达式找到"#### **表格开始**"和"#### **表格结束**"之间的内容
        markdown_table = re.search(r'#### \*\*Start\*\*(.*?)#### \*\*End\*\*', markdown_table, re.DOTALL).group(1)

        # 使用正则表达式找到表头
        headers = re.search(r'\|(.+)\|', markdown_table).group(1).split('|')

        # 移除表头后的所有空格，并去除第一个和最后一个元素（它们是空字符串）
        headers = [header.strip() for header in headers if header.strip()]

        # 使用正则表达式找到除表头外的所有行
        rows = re.findall(r'\|(.+)\|', markdown_table)[1:]

        # 清理每行数据，去除竖线、空格，并分割成列表
        data = [row.strip().split('|') for row in rows]

        # 移除每行中的空字符串
        data = [list(filter(None, row)) for row in data]

        # 移除第五列的数据
        for row in data:
            if len(row) >= 5:
                del row[4]  # 删除第五列

        # 移除第五个表头
        if len(headers) >= 5:
            del headers[4]

        # 创建DataFrame
        df = pd.DataFrame(data, columns=headers)
        #将第一行清理掉. 避免报错 "0  :----:  -------"
        df.drop(df.index[0], inplace=True)
        return df

    def create_unique_name_address_table(self, df):
        # 查找Name和Address的唯一组合
        unique_df = df.drop_duplicates(subset=['Name', 'Address'])

        # 查找所有重复的Name
        duplicates = df[df.duplicated('Name', keep=False)]

        # 检查Name和Address的组合是否一致
        errors = []
        for name, group in duplicates.groupby('Name'):
            # 如果Name对应多个不同的Address，记录下来
            if len(group['Address'].unique()) > 1:
                errors.append(group)

        # 打印错误信息
        if errors:
            print("[ERROR]检测到错误地址表:")
            for error in errors:
                print(error)
        else:
            print("[SUCCESS]地址表生成完毕")

        # 返回没有错误的唯一Name和Address表
        return unique_df[['Name', 'Address']]

    def test_print_function(self, df):
        # 检查传入的DataFrame是否包含'Function'列
        if 'Function' not in df.columns:
            raise KeyError("DataFrame does not contain 'Function' column.")
        # 按顺序遍历DataFrame的每一行
        for index, row in df.iterrows():
            function = str(row['Function']).strip()  # 修剪字符串以移除前导和尾随空格
            # print(f"当前行: {index}, 函数: {function}")
            name = row.get('Name', 'default_name')
            data = row.get('Data', 'default_data')

            if function == 'WE':
                print(f"write({name.strip()}, {data.strip()})")  # 同样修剪name和data
            elif function == 'RE':
                print(f"read({name.strip()}, {data.strip()})")  # 同样修剪name和data
            else:
                print(f"test({name.strip()}, {data.strip()})")  # 同样修剪name和data

    def create_register_config_file(self, df, file_name):
        #创建配置c源文件
        creator = WriteConfigCreator(file_name)
        # 检查传入的DataFrame是否包含'Function'列
        if 'Function' not in df.columns:
            raise KeyError("DataFrame does not contain 'Function' column.")
        # 按顺序遍历DataFrame的每一行
        for index, row in df.iterrows():
            function = str(row['Function']).strip()  # 修剪字符串以移除前导和尾随空格
            # print(f"当前行: {index}, 函数: {function}")
            name = row.get('Name', 'default_name')
            name = name.strip()
            data = row.get('Data', 'default_data')
            data = data.strip()

            if function == 'WE':
                print(f"write({name.strip()}, {data.strip()})")  # 同样修剪name和data
                #生成配置命令
                creator.write_config(name, int(data, 16))
    
    def create_read_register_file(self, df, file_name):

        # 使用正则表达式匹配所有RE后跟数字（可选）和冒号后跟任意非空白字符的模式
        print(f"正在读取文件: {file_name}")
        print(self.formula)
        matches = re.findall(r'RE\d+: data = (.+?);', self.formula)
        # 创建一个字典来存储变量名和对应的值
        variables = {}
        # 填充字典
        for i, value in enumerate(matches):
            variables[f're{i}'] = "data = " + value + ";"
        # 检查传入的DataFrame是否包含'Function'列
        if 'Function' not in df.columns:
            raise KeyError("DataFrame does not contain 'Function' column.")
        # 创建一个字典来存储每个 'RE0' 到 'RE5' 值的打印状态
        printed_status = {'RE0': False, 'RE1': False, 'RE2': False, 'RE3': False, 'RE4': False, 'RE5': False}
        for index, row in df.iterrows():
            # 获取 'function' 列的值
            function_value =  str(row['Function']).strip() 
            # 检查 'function' 列的值是否在指定的列表中，并且还没有被打印过
            if function_value in printed_status and not printed_status[function_value]:
                if function_value == 'RE0':
                    creator0 = ReadRegisterCreator(file_name,0,variables.get('re0', "//None;"))
                if function_value == 'RE1':
                    creator1 = ReadRegisterCreator(file_name,1,variables.get('re1', "//None;"))
                if function_value == 'RE2':
                    creator2 = ReadRegisterCreator(file_name,2,variables.get('re2', "//None;"))
                if function_value == 'RE3':
                    creator3 = ReadRegisterCreator(file_name,3,variables.get('re3', "//None;"))
                if function_value == 'RE4':
                    creator4 = ReadRegisterCreator(file_name,4,variables.get('re4', "//None;"))
                if function_value == 'RE5':
                    creator5 = ReadRegisterCreator(file_name,5,variables.get('re5', "//None;"))
                print(f"Function: {function_value} has been found.")
                # 更新打印状态为 True，表示该值已经被打印过
                printed_status[function_value] = True
        # 按顺序遍历DataFrame的每一行
        for index, row in df.iterrows():
            function = str(row['Function']).strip()  # 修剪字符串以移除前导和尾随空格
            # print(f"当前行: {index}, 函数: {function}")
            name = row.get('Name', 'default_name')
            name = name.strip()
            data = row.get('Data', 'default_data')
            data = data.strip()

            if function == 'RE0':
                print(f"read0({name.strip()}, {data.strip()})")  # 同样修剪name和data
                #生成配置命令
                creator0.read_config(name.strip(), str(data.strip()))
            if function == 'RE1':
                print(f"read1({name.strip()}, {data.strip()})")  # 同样修剪name和data 
                #生成配置命令
                creator1.read_config(name.strip(), str(data.strip()))
            if function == 'RE2':
                print(f"read2({name.strip()}, {data.strip()})")  # 同样修剪name和data
                #生成配置命令   
                creator2.read_config(name.strip(), str(data.strip()))
            if function == 'RE3':
                print(f"read3({name.strip()}, {data.strip()})")  # 同样修剪name和data
                #生成配置命令
                creator3.read_config(name.strip(), str(data.strip()))
            if function == 'RE4':
                print(f"read4({name.strip()}, {data.strip()})")
                #生成配置命令
                creator4.read_config(name.strip(), str(data.strip()))
            if function == 'RE5':
                print(f"read5({name.strip()}, {data.strip()})")
                #生成配置命令
                creator5.read_config(name.strip(), str(data.strip()))

                
####################################################################################
def test_main():
    # 调用函数并传入Markdown文件的路径
    markdown_file_path = './Register_Config.md'  # 替换为你的Markdown文件路径
    processor = MarkdownTableProcessor(markdown_file_path)

    print("总表")
    print(processor.df)

    print("寄存器表")
    print(processor.unique_df)
    # 打印'Function'列的数据
    print("命令表")
    processor.test_print_function(processor.df)####################################################################################
def test_create_register_files():
    # 调用函数并传入Markdown文件的路径
    markdown_file_path = './Register_Config.md'  # 替换为你的Markdown文件路径
    processor = MarkdownTableProcessor(markdown_file_path)

    print("总表")
    print(processor.df)

    print("寄存器表")
    print(processor.unique_df)
    #将第一行清理掉. 避免报错 "0  :----:  -------"
    processor.unique_df.drop(processor.unique_df.index[0], inplace=True)

    # print("命令表")
    # processor.print_function_commands()
    ################################################
    # 创建寄存器文件
    creator = RegisterFileCreator("example")
    for index, row in processor.unique_df.iterrows():
        # 检查Address是否为有效的十六进制数
        try:
            address = int(row['Address'], 16)
            creator.create_register_files(row['Name'], address)
        except ValueError:
            print(f"无法解析地址 '{row['Address']}' 为十六进制数。")
#################################################################################### 
####################################################################################  
def test_all(markdown_file_path1, file_name1):

    # 调用函数并传入Markdown文件的路径
    # markdown_file_path = './Register_Config.md'  # 替换为你的Markdown文件路径
    markdown_file_path = markdown_file_path1
    processor = MarkdownTableProcessor(markdown_file_path)
    # file_name = "test"
    file_name = file_name1
    print("总表")
    print(processor.df)

    print("寄存器表")
    print(processor.unique_df)
    
    # 创建寄存器文件
    creator = RegisterFileCreator(file_name)
    for index, row in processor.unique_df.iterrows():
        # 检查Address是否为有效的十六进制数
        try:
            address = int(row['Address'], 16)
            creator.create_register_files(row['Name'].strip(), address)
        except ValueError:
            print(f"无法解析地址 '{row['Address']}' 为十六进制数。")
    #创建命令文件
    print("命令表")
    processor.create_register_config_file(processor.df,file_name)
    #创建读取寄存器文件
    print("读取寄存器表")
    processor.create_read_register_file(processor.df,file_name)
    # print("打印表")
    # processor.test_print_function(processor.df)
####################################################################################

if __name__ == "__main__":
    # test_main()
    # test_create_register_files()
    # test_create_write_config()
    # test_all('./Register_Config.md', "test")
    if len(sys.argv) != 3:
        print("Usage: xxx <argument1> <argument2>")
        sys.exit(1)
    test_all(sys.argv[1], sys.argv[2])
   

